package globalVisionEntertainment.nba;

import gqqnbig.Tuple;

import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.SimpleTimeZone;

public class PlayerPairScoreGain
{
	private final static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	private final static SimpleDateFormat inQuarterTimeFormat = new SimpleDateFormat("HH:mm:ss");

	static
	{
		inQuarterTimeFormat.setTimeZone(new SimpleTimeZone(0, "UTC"));
	}

	final PartyPlayerScoreGain homeGain;
	final PartyPlayerScoreGain visitorGain;

	double totalGain;

	public PlayerPairScoreGain(String homePlayer, String visitorPlayer)
	{
		homeGain = new PartyPlayerScoreGain(homePlayer);
		visitorGain = new PartyPlayerScoreGain(visitorPlayer);
	}

	/**
	 * 
	 * @param beforeDate
	 * @return 返回false如果没有这两个球员的配对记录。
	 */
	boolean findScoreGain(Connection connection, String beforeDate) throws UnsupportedOperationException
	{
		if (homeGain.proportionalOnCourtMinutes == 0 || visitorGain.proportionalOnCourtMinutes == 0)
			throw new UnsupportedOperationException("proportionalOnCourtMinutes cannot be 0.");

		HashMap<String, Double> onCourtMap = new HashMap<>();
		HashMap<String, Integer> scoreMap = new HashMap<>();

		onCourtMap.put(homeGain.playerName, 0d);
		onCourtMap.put(visitorGain.playerName, 0d);
		scoreMap.put(homeGain.playerName, 0);
		scoreMap.put(visitorGain.playerName, 0);

		try
		{

			CallableStatement statement = connection.prepareCall("{CALL `nba`.`getCommonGames`(?, ?, ?)}");
			statement.setString(1, homeGain.playerName);
			statement.setString(2, visitorGain.playerName);
			statement.setString(3, beforeDate);
			ResultSet resultSet = statement.executeQuery();
			resultSet.beforeFirst();
			ArrayList<String> gameIds = new ArrayList<String>();
			while (resultSet.next())
				gameIds.add(resultSet.getString(1));

			if (NbaScorePredictor.verbose || System.getProperty("debug", "false").equals("true"))
				System.out.printf("%3$d games have both %1$s and %2$s.\n", homeGain.playerName, visitorGain.playerName, gameIds.size());

			int onCourtSconds = 0;
			int score = 0;
			for (String id : gameIds)
			{
				getInQuarterMatchup(connection, id, onCourtMap, scoreMap);
			}

			homeGain.scoreGain = scoreMap.get(homeGain.playerName) / onCourtMap.get(homeGain.playerName);
			visitorGain.scoreGain = homeGain.scoreGain;

			totalGain = homeGain.proportionalOnCourtMinutes * homeGain.scoreGain + visitorGain.proportionalOnCourtMinutes
					* visitorGain.scoreGain;
			return true;
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	/**
	 * 
	 * @param connection
	 * @param gameId
	 * @param onCourtMap
	 *            Unit is minutes.
	 * @param scoreMap
	 * @return
	 * @throws SQLException
	 */
	private void getInQuarterMatchup(Connection connection, String gameId, HashMap<String, Double> onCourtMap,
			HashMap<String, Integer> scoreMap) throws SQLException
	{

		ArrayList<PlayerInQuarterStatistic> stat1 = getInQuarterStats(connection, gameId, homeGain.playerName);
		ArrayList<PlayerInQuarterStatistic> stat2 = getInQuarterStats(connection, gameId, visitorGain.playerName);

		if (NbaScorePredictor.verbose || System.getProperty("debug", "false").equals("true"))
			System.out.printf("Game: %s\n", gameId);

		for (PlayerInQuarterStatistic p1 : stat1)
		{
			for (PlayerInQuarterStatistic p2 : stat2)
			{
				if (p1.quarter == p2.quarter)
				{
					Date enterTime;
					int enterP1Score;
					int enterP2Score;

					Date leaveTime;
					int leaveP1Score;
					int leaveP2Score;

					// p1: 12:00
					// p2: 10:00
					// we use p2.
					if (p2.getEnterTime().before(p1.getEnterTime()))
					{
						enterTime = p2.getEnterTime();
						enterP2Score = p2.enterMyScore;
						enterP1Score = p2.enterRivalScore;
					}
					else
					{
						enterTime = p1.getEnterTime();
						enterP1Score = p1.enterMyScore;
						enterP2Score = p1.enterRivalScore;
					}

					// p1: 5:00
					// p2: 3:00
					// we use p1.
					if (p2.getLeaveTime().before(p1.getLeaveTime()))
					{
						leaveTime = p1.getLeaveTime();
						leaveP1Score = p1.leaveMyScore;
						leaveP2Score = p1.leaveRivalScore;
					}
					else
					{
						leaveTime = p2.getLeaveTime();
						leaveP2Score = p2.leaveMyScore;
						leaveP1Score = p2.leaveRivalScore;
					}

					double onCourtMinutes = (enterTime.getTime() - leaveTime.getTime()) / 1000.0 / 60;
					if (onCourtMinutes > 0)
					{
						int score = leaveP1Score - enterP1Score + leaveP2Score - enterP2Score;

						onCourtMap.put(homeGain.playerName, onCourtMap.get(homeGain.playerName) + onCourtMinutes);
						scoreMap.put(homeGain.playerName, scoreMap.get(homeGain.playerName) + score);

						if (NbaScorePredictor.verbose || System.getProperty("debug", "false").equals("true"))
						{
							System.out.printf("Quarter %d, ", p1.quarter);
							System.out
									.printf("Enter court %s (%d-%d), ", inQuarterTimeFormat.format(enterTime), enterP1Score, enterP2Score);
							System.out
									.printf("Leave court %s (%d-%d)\n", inQuarterTimeFormat.format(leaveTime), leaveP1Score, leaveP2Score);

						}

						break;
					}
				}
			}
		}
	}

	private ArrayList<PlayerInQuarterStatistic> getInQuarterStats(Connection connection, String gameId, String playerName)
			throws SQLException
	{
		try
		{

			PreparedStatement statement = connection
					.prepareStatement("select * from player_in_quarter_statistic where game=? and `playername`=?");
			statement.setString(1, gameId);
			statement.setString(2, playerName);

			ResultSet resultSet = statement.executeQuery();
			resultSet.beforeFirst();
			ArrayList<PlayerInQuarterStatistic> stat1 = new ArrayList<>();
			while (resultSet.next())
			{
				int quarter = resultSet.getInt(3);
				java.util.Date enterTime = inQuarterTimeFormat.parse(resultSet.getString(4));
				java.util.Date leaveTime = inQuarterTimeFormat.parse(resultSet.getString(5));
				int enterMyScore = resultSet.getInt(6);
				int enterRivalScore = resultSet.getInt(7);
				int leaveMyScore = resultSet.getInt(8);
				int leaveRivalScore = resultSet.getInt(9);

				PlayerInQuarterStatistic p = new PlayerInQuarterStatistic(playerName, enterTime);
				p.quarter = quarter;
				p.setEndTime(leaveTime);
				p.enterMyScore = enterMyScore;
				p.enterRivalScore = enterRivalScore;
				p.leaveMyScore = leaveMyScore;
				p.leaveRivalScore = leaveRivalScore;

				stat1.add(p);
			}

			return stat1;
		}
		catch (ParseException e)
		{
			throw new RuntimeException(e);
		}
	}
}
